package edu.bath.sensors.powersensor;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import edu.bath.sensorframework.DataReading;

public class PowerReading {
	private String src;
	private int dsb;
	private String time;
	private float temperature;
	private int applianceNumber;
	private int radioId;
	private SensorType type;
	private List<Map<String, String>> data = new ArrayList<Map<String, String>>();
	
	private String currentLocation;
	private String primaryHandle;
	
	public enum SensorType {
		ELECTRICITY, UNKNOWN;
	}
	
	public DataReading toDataReadingPwr() {
		DataReading dr =  new DataReading(getPrimaryHandle(), getCurrentLocation(), System.currentTimeMillis());
		dr.setType("http://bath.edu/sensors/types#Power");
		
		for(Map<String, String> channel : data) {
			Double watts = Double.parseDouble(channel.get("watts"));
			dr.addDataValue(null, "http://bath.edu/sensors/types#watts", watts, false);
		}
		
		return dr;
	}
	
	public DataReading toDataReadingTemp() {
		DataReading dr =  new DataReading(getPrimaryHandle(), getCurrentLocation(), System.currentTimeMillis());
		dr.setType("http://bath.edu/sensors/types#Temperature");
		
		dr.addDataValue(null, "http://bath.edu/sensors/types#celsius", new Float(temperature), false);
		
		return dr;
	}
	
	public float getTemperature() { return this.temperature; }
	
	public static PowerReading fromXML(String xml) throws SAXException, IOException, ParserConfigurationException {
		PowerReading pr = new PowerReading();
		
		DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = fact.newDocumentBuilder();
		Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
		Node rootNode = doc.getDocumentElement();
		
		Node node = null;
		NodeList children = rootNode.getChildNodes();
		for(int i = 0 ; i < children.getLength() ; i++) {
			node = children.item(i);
			String name = node.getNodeName();
			String value = node.getFirstChild().getNodeValue();
			if(name.equals("src"))
				pr.src = value;
			else if(name.equals("time"))
				pr.time = value;
			else if(name.equals("tmpr"))
				pr.temperature = Float.parseFloat(value);
			else if(name.equals("dsb"))
				pr.dsb = Integer.parseInt(value);
			else if(name.equals("sensor"))
				pr.applianceNumber = Integer.parseInt(value);
			else if(name.equals("id"))
				pr.radioId = Integer.parseInt(value);
			else if(name.equals("type")) {
				int type = Integer.parseInt(value);
				switch(type) {
				case 1:
					pr.type = SensorType.ELECTRICITY;
					break;
				default:
					pr.type = SensorType.UNKNOWN;
					break;
				}
			} else if(name.startsWith("ch")) {
				NodeList chNodes = node.getChildNodes();
				Map<String, String> map = new HashMap<String, String>();
				
				for(int j = 0 ; j < chNodes.getLength() ; j++) {
					Node n = chNodes.item(j);
					map.put(n.getNodeName(), n.getFirstChild().getNodeValue());
				}
				pr.data.add(map);
			} else if(name.equals("hist")) {
				System.out.println("Ignoring hist..");
				throw new RuntimeException();
			} else {
				throw new IOException("Unknown node type '"+name+"'.");
			}
		}
//		Log.console("Temperature is currently.. "+pr.temperature);
//		Log.console("Raw XMl was... '"+xml+"'");
		
		return pr;
	}
	
	public String toString() {
		String output = "";
		
		output += "src = " + src + "\n";
		output += "dsb = " + dsb + "\n";
		output += "time = " + time + "\n";
		output += "tmpr = " + temperature + "\n";
		output += "sensor = " + applianceNumber + "\n";
		output += "id = " + radioId + "\n";
		output += "type = " + type + "\n";
		for(int i = 0 ; i < data.size() ; i++) {
			Map<String, String> dat = data.get(i);
			output += "   ch"+(i+1)+" = ";
			for(String key : dat.keySet()) {
				String val = dat.get(key);
				output += "["+key+", "+val+"] ";
			}
		}

		return output;
	}

	public String getCurrentLocation() {
		return currentLocation;
	}

	public void setCurrentLocation(String currentLocation) {
		this.currentLocation = currentLocation;
	}

	public String getPrimaryHandle() {
		return primaryHandle;
	}

	public void setPrimaryHandle(String primaryHandle) {
		this.primaryHandle = primaryHandle;
	}
}
